import LineChart from "./components/LineChart.svelte";
import PieChart from "./components/PieChart.svelte";
import GaugeChart from "./components/GaugeChart.svelte";
import ToastContainer from "./components/ToastContainer.svelte";
import Modal from "./components/Modal.svelte";
import DataTable from "./components/DataTable.svelte";
import BoxplotChart from "./components/BoxplotChart.svelte";

const registry = {
  LineChart,
  PieChart,
  GaugeChart,
  ToastContainer,
  Modal,
  DataTable,
  BoxplotChart
};

const mounted = new WeakMap();

function parseDataset(dataset) {
  const props = {};
  for (const [key, value] of Object.entries(dataset)) {
    if (key === "svelteComponent") continue;
    const raw = typeof value === "string" ? value.trim() : value;

    if (raw === "true" || raw === "false") {
      props[key] = raw === "true";
      continue;
    }

    if (typeof raw === "string" && raw.length > 0 && (raw.startsWith("{") || raw.startsWith("["))) {
      try {
        props[key] = JSON.parse(raw);
        continue;
      } catch (err) {
        console.warn(`Failed to parse JSON dataset for key "${key}"`, err);
      }
    }

    if (typeof raw === "string" && raw !== "" && !Number.isNaN(Number(raw))) {
      props[key] = Number(raw);
      continue;
    }

    props[key] = raw;
  }
  return props;
}

function mountComponents(root = document) {
  const nodes = root.querySelectorAll("[data-svelte-component]");
  nodes.forEach((node) => {
    if (mounted.has(node)) {
      return;
    }
    const componentName = node.dataset.svelteComponent;
    const Component = registry[componentName];
    if (!Component) {
      console.warn(`Unknown Svelte component: ${componentName}`);
      return;
    }

    const props = parseDataset(node.dataset);
    const instance = new Component({ target: node, props });
    mounted.set(node, instance);
  });
}

function cleanupNode(node) {
  const instance = mounted.get(node);
  if (instance) {
    instance.$destroy();
    mounted.delete(node);
  }
}

function observeRemovals() {
  const observer = new MutationObserver((mutations) => {
    mutations.forEach((mutation) => {
      mutation.removedNodes.forEach((removed) => {
        if (!(removed instanceof HTMLElement)) return;
        if (removed.dataset?.svelteComponent) {
          cleanupNode(removed);
        }
        removed.querySelectorAll?.("[data-svelte-component]").forEach(cleanupNode);
      });
    });
  });

  observer.observe(document.body, { childList: true, subtree: true });
}

if (document.readyState === "loading") {
  document.addEventListener("DOMContentLoaded", () => {
    mountComponents();
    observeRemovals();
  });
} else {
  mountComponents();
  observeRemovals();
}

if (window.htmx) {
  document.body.addEventListener("htmx:afterSwap", (event) => {
    mountComponents(event.target);
  });
  document.body.addEventListener("htmx:afterSettle", (event) => {
    mountComponents(event.target);
  });
  document.body.addEventListener("htmx:beforeSwap", (event) => {
    if (!(event.target instanceof HTMLElement)) return;
    if (event.target.dataset?.svelteComponent) {
      cleanupNode(event.target);
    }
    event.target.querySelectorAll?.("[data-svelte-component]").forEach(cleanupNode);
  });
}
